﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AzureGames.Model;
using AzureGames.Common;


namespace AzureGames.Data.InMemory
{
    public class NotificationRepository : INotificationRepository
    {
        object _lock = new object();

        // this is made static to simulate a persistant environment
        static List<string> _playersToNotify = new List<string>();

        static List<Notification> _notifications = new List<Notification>();

        public void Attach(string playerID)
        {
            _playersToNotify.Add(playerID);

            PushNotifications(playerID);
        }

        public void Detach(string playerID)
        {
            _playersToNotify.Remove(playerID);
        }

        public void PostNotification(Model.Notification message)
        {
            // with azure storage this would add the action to a queue
            // this would then trigger the notify to be sent
            // if the notify request results in true
            // then the action is removed from the queue
            // if it is false then it probably indicates has logged off
            // the message will then stay in the queue until they are logged in again
            // and in the play game view again

            // add to storage
            lock (_lock)
            {
                // create a copy as to make sure that references are new to similate the message coming from the repository
                var notification = new Notification
                    {
                        BoardID = message.BoardID,
                        CreatedDate = message.CreatedDate,
                        Data = message.Data,
                        GameDefinitionID = message.GameDefinitionID,
                        ID = message.ID,
                        LastUpdatedDate = message.LastUpdatedDate,
                        Message = message.Message,
                        PlayerID = message.PlayerID,
                        State = message.State
                    };

                _notifications.Add(notification);
            }

            // trigger the listener
            if (message.PlayerID == Guid.Empty.ToString() || _playersToNotify.Contains(message.PlayerID))
                PushNotification(message);
        }

        public event NotifyEventHandler NotifyEvent;

        public void PushNotifications(string playerID)
        {
            // send notifications to observers
            if (NotifyEvent != null)
            {
                lock (_lock)
                {
                    _notifications.Where(n => n.PlayerID == playerID && n.State==Notification.STATE.Pending).ForEach(message => NotifyEvent(this, new NotifyEventArgs { Message = message }));
                }
            }
        }

        public void PushNotification(Model.Notification message)
        {
            if (NotifyEvent != null)
            {
                // if the message was acknowledged or it was an anonymous message
                if (NotifyEvent(this, new NotifyEventArgs { Message = message }) || message.PlayerID == Guid.Empty.ToString())
                    message.State = Notification.STATE.Delivered;
            }
        }

        public void UpdateState(Guid messageID, Notification.STATE state)
        {
            lock (_lock)
            {
                _notifications.First(n => n.ID == messageID).State = state;
            }
        }        
    }
}
